<script lang="ts" setup>
import type { FormInst, FormItemRule, FormRules, TreeOption } from 'naive-ui'
import { NButton, NTag } from 'naive-ui'
import Cimage from '@/components/Cimage/index.vue'
import { categoryDelete, categoryGetOne, categoryGetTwo, categoryModify } from '@/api/category'
import type { CategoryGetReturnItemModel } from '@/api/category'
import type { FileItemModel } from '@/api/file'

const categoryAdminListDialogRef = ref<FormInst | null>(null)

/** 初始化数据 */
const categoryData = ref<TreeOption[]>([])
async function getList() {
  const { code: codeOne, data: categoryDataOne } = await categoryGetOne()
  const { code: codeTwo, data: categoryDataTwo } = await categoryGetTwo()
  if (codeOne === 0 && codeTwo === 0) {
    categoryData.value = categoryDataOne.map((item) => {
      const itemData: TreeOption = {
        key: `s${item.id}`,
        label: item.name,
        children: [],
        level: 1,
        suffix: () => {
          return [
            h(
              NButton,
              {
                text: true,
                type: 'default',
                class: 'mr5',
                onClick(e) {
                  e.stopPropagation()
                  openDialog(`修改分类—${item.name}`, 'modify', 'one', item)
                },
              },
              { default: () => '修 改' },
            ),
            h(
              NButton,
              {
                text: true,
                type: 'info',
                class: 'mr5 ml5',
                onClick(e) {
                  e.stopPropagation()
                  openDialog(`新增子类—${item.name}`, 'add', 'two', item, item.id)
                },
              },
              { default: () => '新增子类' },
            ),
            h(
              NButton,
              {
                text: true,
                type: 'error',
                class: 'ml5 mr10',
                onClick(e) {
                  e.stopPropagation()
                  openTips(item.id, 'one')
                },
              },
              { default: () => '删除全部' },
            ),
          ]
        },
      }
      categoryDataTwo?.forEach((val) => {
        if (item.id === val.parentId) {
          itemData.children?.push({
            label: val.name,
            key: val.id,
            level: 2,
            parentId: val.parentId,
            icon: val.icon![0].url,
            suffix: () => {
              return [
                h(
                  NButton,
                  {
                    text: true,
                    type: 'info',
                    class: 'mr5',
                    onClick(e) {
                      e.stopPropagation()
                      openDialog(`修改分类—${val.name}`, 'modify', 'two', val, item.parentId)
                    },
                  },
                  { default: () => '修 改' },
                ),
                h(
                  NButton,
                  {
                    text: true,
                    type: 'error',
                    class: 'ml5 mr10',
                    onClick(e) {
                      e.stopPropagation()
                      openTips(val.id, 'two')
                    },
                  },
                  { default: () => '删 除' },
                ),
              ]
            },
          })
        }
      })
      return itemData
    })
  }
}

// 表格内容渲染函数
function renderLabel({ option }: { option: TreeOption }) {
  if (option.level === 1) {
    return [
      h(NTag, { bordered: false, type: 'primary', class: 'mr15' }, () => option.children?.length),
      h('div', option.label),
    ]
  }
  else if (option.level === 2) {
    return [
      h(Cimage, {
        width: '30',
        height: '30',
        previewDisabled: true,
        src: option.icon as string,
        class: 'mr10',
      }),
      h('div', option.label),
    ]
  }
}

/** 模态框 */
interface Dialog {
  visible: boolean
  title: string
  id?: string | number // 不传或空为新增，传为修改
  parentId?: string | number // 父级Id
  name: string
  icon?: string
  type: string // 类型描述
  className: string // 传one || two （一级或二级）
}
const dialog = ref<Dialog>({
  visible: false,
  title: '',
  name: '',
  type: '',
  icon: '',
  className: '',
})
const iconList = ref<FileItemModel[] | undefined>([])
function openDialog(title: string, type: string, level: string, row?: CategoryGetReturnItemModel, parentId?: number | string) { // 打开模态框
  dialog.value.title = title
  dialog.value.visible = true
  dialog.value.className = level
  dialog.value.parentId = parentId || ''

  if (type === 'modify') {
    dialog.value.icon = row?.icon ? row.icon[0].id.toString() : ''
    dialog.value.id = row!.id
    dialog.value.name = row!.name
    dialog.value.type = row!.type

    iconList.value = row!.icon
  }
}

function closeDialog() { // 关闭模态框
  dialog.value = {
    visible: false,
    title: '',
    name: '',
    type: '',
    icon: '',
    className: '',
    id: undefined,
    parentId: undefined,
  }
  categoryAdminListDialogRef.value?.restoreValidation() // 清空校验
}
async function submitDialog() { // 提交表单
  categoryAdminListDialogRef.value?.validate((errors) => {
    if (!errors)
      categoryModifyApi()
    else
      window.$message?.warning('请输入相应必填项')
  })
}
async function categoryModifyApi() { // 修改接口
  const { code, msg } = await categoryModify({
    className: dialog.value.className,
    name: dialog.value.name,
    type: dialog.value.type,
    id: dialog.value.id ? dialog.value.id : undefined,
    icon: dialog.value.icon ? dialog.value.icon : undefined,
    parentId: dialog.value.parentId ? dialog.value.parentId : undefined,
  })
  if (code === 0) {
    window.$message?.success(msg)
    getList()
    closeDialog()
  }
}
/** 表单校验 */
const rulesFunction = {
  uploadValidator(_rule: FormItemRule, value: string): boolean {
    console.log(_rule, value, '表单检验')
    return !!value
  },
}
const rules: FormRules = {
  icon: [{ required: true, message: '请上传分类封面', trigger: 'change', validator: (rulesFunction.uploadValidator) }],
  name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
  type: [{ required: true, message: '请输入分类类型描述', trigger: 'blur' }],
}

/** 删除分类  */
function openTips(id: number, className: string) {
  window.$dialog?.warning({
    title: '提示',
    content: '确定执行此操作吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      removeCategory(id, className)
    },
  })
}
async function removeCategory(id: number, className: string) { // 删除接口
  const { code, msg } = await categoryDelete({ id, className })
  if (code === 0) {
    window.$message?.success(msg)
    getList()
  }
}
onMounted(() => {
  getList()
})
</script>

<template>
  <AppPage>
    <NButton strong secondary mb10 type="primary" style="width: fit-content;" @click="openDialog('添加一级分类', 'add', 'one')">
      添加一级分类
    </NButton>
    <n-tree
      block-line
      block-node
      expand-on-click
      check-strategy="child"
      :data="categoryData"
      accordion
      :render-label="renderLabel"
    />
  </AppPage>
  <Cdialog v-model:visible="dialog.visible" :title="dialog.title" @close-modal="closeDialog">
    <n-form
      ref="categoryAdminListDialogRef"
      size="medium"
      label-placement="top"
      :model="dialog"
      :rules="rules"
    >
      <n-form-item v-if="dialog.className !== 'one'" label="分类封面" path="icon">
        <CuploadImage v-model:imageIds="dialog.icon" :default-file-list="iconList" :max="1" width="100px" height="100px" />
      </n-form-item>
      <n-form-item label="分类名称" path="name">
        <n-input v-model:value="dialog.name" placeholder="输入分类名称" />
      </n-form-item>
      <n-form-item label="类型描述" path="type">
        <n-input v-model:value="dialog.type" placeholder="输入类型描述" />
      </n-form-item>
    </n-form>
    <template #footer>
      <n-space justify="center">
        <NButton b-rd-5 size="medium" @click="closeDialog">
          <n-icon cursor-pointer size="16">
            <icon-mdi:cancel />
          </n-icon>
          <span ml-2>取 消</span>
        </NButton>
        <NButton b-rd-5 type="primary" size="medium" @click="submitDialog">
          <n-icon cursor-pointer size="16">
            <icon-mdi:checkbox-marked-circle-outline />
          </n-icon>
          <span ml-2>确 定</span>
        </NButton>
      </n-space>
    </template>
  </Cdialog>
</template>

<style lang="scss" scoped>
.n-tree {
  & :deep(.n-tree-node-wrapper){
    padding: 0;
    background-color: #fff;
    border-radius: 6px;
    margin-bottom: 15px;
    height: 40px;
  }
  & :deep(.n-tree-node) {
    height: 100%;
    align-items: center;
  }
  & :deep(.n-tree-node-content .n-tree-node-content__text) {
    display: flex;
    align-items: center;
  }
}
</style>
